package com.genexususa.eo.bing.connection;

import com.genexususa.eo.bing.CampaignManagementServiceClasses.*;
import com.genexususa.eo.bing.data.*;
import com.genexususa.eo.bing.data.Util;
import com.genexususa.eo.bing.data.requests.GxKeywordDestinationUrlsAdGroupRequest;
import com.genexususa.eo.bing.data.requests.GxKeywordDestinationUrlsRequest;
import com.genexususa.eo.bing.data.requests.GxKeywordsAdGroupRequest;
import com.genexususa.eo.bing.data.requests.GxKeywordsRequest;
import com.genexususa.eo.bing.data.results.GxElementsAdGroupsResult;
import com.genexususa.eo.bing.data.results.GxElementsCampaignsResult;
import com.genexususa.eo.bing.data.results.GxElementsResults;
import com.genexususa.eo.bing.data.util.BingKeyword;
import com.genexususa.eo.bing.data.util.BingTextAd;
import com.genexususa.eo.bing.data.wsSubclasses.*;
import com.genexususa.eo.google.data.*;
import com.genexususa.eo.google.data.Error;
import org.apache.axis.AxisFault;
import org.xml.sax.SAXException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.rpc.ServiceException;
import java.io.IOException;
import java.io.StringWriter;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;

public class KeywordManager {
    public KeywordManager() {
    }

    public String addKeywords(long customerAccountId, String keywordsRequestsXML) {

        ICampaignManagementService campaignManagement = null;
        CampaignManagementServiceLocator campaignServiceLocator = null;
        BasicHttpBinding_ICampaignManagementServiceStub stub = null;
        AddKeywordsRequest addKeywordsRequest = null;
        AddKeywordsResponse addKeywordsResponse = null;
        GA_Result result = new GA_Result();
        Util util = new Util();
        GxKeywordsRequest[] keywordsRequests = null;
        GxKeywordsAdGroupRequest keywordsAdGroupRequest = null;
        try {

            HashMap<String, String> properties = Info.getBingProperties();
            String namespace = properties.get("campaignNamespace");
            String url = properties.get("campaignURL");
            String userName = properties.get("username");
            String password = properties.get("password");
            String developerToken = properties.get("developerToken");
            String customerId = properties.get("customerId");
            String applicationToken = properties.get("applicationToken");

            campaignServiceLocator = new CampaignManagementServiceLocator();
            campaignServiceLocator.setBasicHttpBinding_ICampaignManagementServiceEndpointAddress(url);
            campaignManagement = campaignServiceLocator.getBasicHttpBinding_ICampaignManagementService(); // ServiceException
            stub = (BasicHttpBinding_ICampaignManagementServiceStub) campaignManagement;

            // Set header parameters
            stub.setHeader(namespace, "UserName", userName);
            stub.setHeader(namespace, "Password", password);
            stub.setHeader(namespace, "DeveloperToken", developerToken);
            stub.setHeader(namespace, "CustomerId", customerId);
            stub.setHeader(namespace, "CustomerAccountId", customerAccountId);
            stub.setHeader(namespace, "ApplicationToken", applicationToken);

            // Parse keywordsRequests from XML
            keywordsRequests = util.keywordsRequestsFromXML(keywordsRequestsXML); // IllegalArgumentException, GxException, ParserConfigurationException, SAXException, IOException
            if (keywordsRequests.length == 0) {
                throw new GxItemException("No KeywordsRequests were found");
            }

            for (int k=0; k<keywordsRequests.length; k++) {

                Long gxCampaignId   = keywordsRequests[k].getGxCampaignId();
                Long bingCampaignId = keywordsRequests[k].getBingCampaignId();



                for (int j=0; j<keywordsRequests[k].getKeywordsAdGroupRequests().length; j++) {
                    keywordsAdGroupRequest = keywordsRequests[k].getKeywordsAdGroupRequests()[j];

                    // Set body parameters
                    addKeywordsRequest = new AddKeywordsRequest();
                    addKeywordsRequest.setAdGroupId(keywordsAdGroupRequest.getBingAdGroupId());

                    try {

                        Keyword[] allKeywords = keywordsAdGroupRequest.getKeywords();
                        Keyword[] chunkedKeywords = null;
                        // max element limit = 1000
                        int chunks = (int)Math.ceil(allKeywords.length / 1000.0);
                        if (chunks <= 1){
                            addKeywordsRequest.setKeywords(allKeywords);

                            addKeywordsResponse = campaignManagement.addKeywords(addKeywordsRequest); // RemoteException, EditorialApiFaultDetail, AdApiFaultDetail

                            for (int i=0; i<addKeywordsResponse.getKeywordIds().length; i++) {
                                GxKeyword gxKW = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);

                                GA_ResultItem resultItem = new GA_ResultItem(addKeywordsResponse.getPartialErrors(), i);

                                resultItem.SubCampaignGxId = gxCampaignId;
                                resultItem.CampaignId = bingCampaignId;
                                resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                                resultItem.AdGroupId = keywordsAdGroupRequest.getBingAdGroupId();
                                resultItem.CriterionGxId = gxKW.getGxId();
                                resultItem.CriterionId = addKeywordsResponse.getKeywordIds()[i];

                                result.Items.add(resultItem);
                            }

                        } else if(chunks > 1) {
                            int counter = 1;
                            int index = 0;
                            int chunkItems = 1000;
                            while (counter <= chunks){
                                if(counter == chunks){
                                    chunkItems = allKeywords.length - index;
                                }

                                chunkedKeywords = new Keyword[chunkItems];
                                for(int i = 0; i < chunkItems ; i++){
                                    chunkedKeywords[i] = allKeywords[index];
                                    index+=1;
                                }
                                index = counter * 1000;
                                counter++;

                                addKeywordsRequest.setKeywords(chunkedKeywords);

                                addKeywordsResponse = campaignManagement.addKeywords(addKeywordsRequest); // RemoteException, EditorialApiFaultDetail, AdApiFaultDetail

                                for (int i=0; i<addKeywordsResponse.getKeywordIds().length; i++) {
                                    GxKeyword gxKW = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);

                                    GA_ResultItem resultItem = new GA_ResultItem(addKeywordsResponse.getPartialErrors(), i);

                                    resultItem.SubCampaignGxId = gxCampaignId;
                                    resultItem.CampaignId = bingCampaignId;
                                    resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                                    resultItem.AdGroupId = keywordsAdGroupRequest.getBingAdGroupId();
                                    resultItem.CriterionGxId = gxKW.getGxId();
                                    resultItem.CriterionId = addKeywordsResponse.getKeywordIds()[i];

                                    result.Items.add(resultItem);
                                }

                                /*
                                trackingId = stub.getResponseHeader(namespace, "TrackingId").getValue();
                                result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setSpecificTrackingId(trackingId);
                                result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setGxAdGroupId(keywordsAdGroupRequest.getGxAdGroupId());
                                result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setBingAdGroupId(keywordsAdGroupRequest.getBingAdGroupId());
                                result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].createElementCollection(keywordsAdGroupRequest.getKeywords().length);
                                for (int i=0; i<addKeywordsResponse.getKeywordIds().length; i++) {
                                    result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].addElementResult(i, ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]).getGxId(), addKeywordsResponse.getKeywordIds()[i]);
                                }
                                */

                            }
                        }

                        // Call WS
                        //addKeywordsResponse = campaignManagement.addKeywords(addKeywordsRequest); // RemoteException, EditorialApiFaultDetail, AdApiFaultDetail

                        // Call succeeded with no errors

                        // Create the return object
                        /*
                        trackingId = stub.getResponseHeader(namespace, "TrackingId").getValue();
                        result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setSpecificTrackingId(trackingId);
                        result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setGxAdGroupId(keywordsAdGroupRequest.getGxAdGroupId());
                        result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setBingAdGroupId(keywordsAdGroupRequest.getBingAdGroupId());
                        result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].createElementCollection(keywordsAdGroupRequest.getKeywords().length);
                        for (int i=0; i<addKeywordsResponse.getKeywordIds().length; i++) {
                            result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].addElementResult(i, ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]).getGxId(), addKeywordsResponse.getKeywordIds()[i]);
                        }
                        */
                    } catch (EditorialApiFaultDetail fault) { // IN CALL
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GA_ResultItem resultItem =  new GA_ResultItem(fault, i);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]).getGxId();

                            result.Items.add(resultItem);
                        }
                    }catch (AxisFault e) { // IN CALL

                        ArrayList<BingKeyword> keywords = getKeywordsByAdGroupId(customerAccountId, keywordsAdGroupRequest.getBingAdGroupId());
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GA_ResultItem resultItem = new GA_ResultItem(e);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]).getGxId();

                            GxKeyword gxKeyword = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);
                            Long isCreated = isCreatedKeyword(keywords, gxKeyword);
                            if (isCreated != 0L){
                                resultItem.HasError = false;
                                resultItem.Errors = null;
                                resultItem.CriterionId = isCreated;
                                resultItem.AdGroupId = keywordsAdGroupRequest.getBingAdGroupId();
                            }
                            else{
                                resultItem.HasError = true;
                                resultItem.Errors = new ErrorsStruct();
                                resultItem.CriterionId = 0L;
                                resultItem.AdGroupId = keywordsAdGroupRequest.getBingAdGroupId();
                                resultItem.Errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();
                                com.genexususa.eo.google.data.Error error = new com.genexususa.eo.google.data.Error();

                                error.ErrorString = "The specified Keyword has one or several errors. Please check Text, URL, params, Bid and Match Type.";
                                resultItem.Errors.Errors.add(error);

                            }
                            result.Items.add(resultItem);

                        }
                    }
                    /*catch (AdApiFaultDetail fault) { // IN CALL
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GA_ResultItem resultItem =  new GA_ResultItem(fault);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]).getGxId();

                            result.Items.add(resultItem);
                        }
                    } */catch (RemoteException e) { // IN CALL
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GA_ResultItem resultItem =  new GA_ResultItem(e);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]).getGxId();

                            result.Items.add(resultItem);
                        }
                    }
                }
            }
        } catch (GxException e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        } catch (Exception e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        }

        String returnMessage = null;
        // GxElementsResults -> XML
        try {
            JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class); // JAXBException

            Marshaller marshallerObj = contextObj.createMarshaller(); // JAXBException
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // PropertyException

            StringWriter sw = new StringWriter();

            marshallerObj.marshal(result, sw); // JAXBException*/
            returnMessage = sw.getBuffer().toString();
        }  catch (PropertyException e) { // AFTER CALL
            returnMessage = util.getPropertyExceptionMessage(e);
        } catch (JAXBException e) { // AFTER CALL
            returnMessage = util.getJAXBExceptionMessage(e);
        }
        return returnMessage;
    }

    public String updateKeywords(long customerAccountId, String keywordsRequestsXML) {
        ICampaignManagementService campaignManagement = null;
        CampaignManagementServiceLocator campaignServiceLocator = null;
        BasicHttpBinding_ICampaignManagementServiceStub stub = null;
        UpdateKeywordsRequest updateKeywordsRequest = null;
        GA_Result result = new GA_Result();
        Util util = new Util();
        GxKeywordsRequest[] keywordsRequests = null;
        GxKeywordsAdGroupRequest keywordsAdGroupRequest = null;
        try {
            HashMap<String, String> properties = Info.getBingProperties();
            String namespace = properties.get("campaignNamespace");
            String url = properties.get("campaignURL");
            String userName = properties.get("username");
            String password = properties.get("password");
            String developerToken = properties.get("developerToken");
            String customerId = properties.get("customerId");
            String applicationToken = properties.get("applicationToken");

            campaignServiceLocator = new CampaignManagementServiceLocator();
            campaignServiceLocator.setBasicHttpBinding_ICampaignManagementServiceEndpointAddress(url);
            campaignManagement = campaignServiceLocator.getBasicHttpBinding_ICampaignManagementService(); // ServiceException
            stub = (BasicHttpBinding_ICampaignManagementServiceStub) campaignManagement;

            // Set header parameters
            stub.setHeader(namespace, "UserName", userName);
            stub.setHeader(namespace, "Password", password);
            stub.setHeader(namespace, "DeveloperToken", developerToken);
            stub.setHeader(namespace, "CustomerId", customerId);
            stub.setHeader(namespace, "CustomerAccountId", customerAccountId);
            stub.setHeader(namespace, "ApplicationToken", applicationToken);

            // Parse keywordsRequests from XML
            keywordsRequests = util.keywordsRequestsFromXML(keywordsRequestsXML); // IllegalArgumentException, GxException, ParserConfigurationException, SAXException, IOException
            if (keywordsRequests.length == 0) {
                throw new GxItemException("No KeywordsRequests were found");
            }

            for (int k=0; k<keywordsRequests.length; k++) {
                Long gxCampaignId = keywordsRequests[k].getGxCampaignId();
                Long bingCampaignId = keywordsRequests[k].getBingCampaignId();

                //result.getElementsCampaignsResultCollection()[k].setGxCampaignId(keywordsRequests[k].getGxCampaignId());
                //result.getElementsCampaignsResultCollection()[k].setBingCampaignId(keywordsRequests[k].getBingCampaignId());
                for (int j=0; j<keywordsRequests[k].getKeywordsAdGroupRequests().length; j++) {
                    keywordsAdGroupRequest = keywordsRequests[k].getKeywordsAdGroupRequests()[j];

                    // Set body parameters
                    updateKeywordsRequest = new UpdateKeywordsRequest();
                    updateKeywordsRequest.setAdGroupId(keywordsAdGroupRequest.getBingAdGroupId());
                    updateKeywordsRequest.setKeywords(keywordsAdGroupRequest.getKeywords());

                    try {
                        // Call WS
                        UpdateKeywordsResponse response = campaignManagement.updateKeywords(updateKeywordsRequest); // RemoteException, EditorialApiFaultDetail, AdApiFaultDetail

                        // Call succeeded with no errors

                        // Create the return object

                        /*result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setSpecificTrackingId(trackingId);
                        result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setGxAdGroupId(keywordsAdGroupRequest.getGxAdGroupId());
                        result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setBingAdGroupId(keywordsAdGroupRequest.getBingAdGroupId());
                        result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].createElementCollection(keywordsAdGroupRequest.getKeywords().length);
                        */
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GxKeyword gxKW = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);

                            GA_ResultItem resultItem = new GA_ResultItem(response.getPartialErrors(), i);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.CampaignId = bingCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.AdGroupId = keywordsAdGroupRequest.getBingAdGroupId();
                            resultItem.CriterionGxId = gxKW.getGxId();
                            resultItem.CriterionId = gxKW.getId();

                            result.Items.add(resultItem);
                        }
                    } catch (EditorialApiFaultDetail fault) { // IN CALL
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GxKeyword gxKW = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);

                            GA_ResultItem resultItem = new GA_ResultItem(fault, i);
                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = gxKW.getId();

                            result.Items.add(resultItem);
                        }
                    } catch (AdApiFaultDetail fault) { // IN CALL


                        ArrayList<BingKeyword> keywords = getKeywordsByAdGroupId(customerAccountId, keywordsAdGroupRequest.getBingAdGroupId());


                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {



                            GA_ResultItem resultItem = new GA_ResultItem(fault);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]).getGxId();

                            GxKeyword gxKeyword = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);
                            Long isCreated = isCreatedKeyword(keywords, gxKeyword);
                            if (isCreated != 0L){
                                resultItem.HasError = false;
                                resultItem.Errors = null;
                                resultItem.CriterionId = isCreated;
                                resultItem.AdGroupId = keywordsAdGroupRequest.getBingAdGroupId();
                            }
                            else{
                                resultItem.HasError = true;
                                resultItem.Errors = new ErrorsStruct();
                                resultItem.CriterionId = 0L;
                                resultItem.Errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();
                                com.genexususa.eo.google.data.Error error = new com.genexususa.eo.google.data.Error();

                                error.ErrorString = "The specified Keyword has one or several errors. Please check Text, URL, params, Bid and Match Type.";
                                resultItem.Errors.Errors.add(error);

                            }
                            result.Items.add(resultItem);

                        }



                        /*for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GxKeyword gxKW = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);

                            GA_ResultItem resultItem = new GA_ResultItem(fault);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = gxKW.getId();

                            result.Items.add(resultItem);
                        }       */
                    } catch (RemoteException e) { // IN CALL
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GxKeyword gxKW = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);

                            GA_ResultItem resultItem = new GA_ResultItem(e);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = gxKW.getId();

                            result.Items.add(resultItem);
                        }
                    }
                }
            }
        } catch (GxException e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        } catch (Exception e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        }

        String returnMessage = null;
        // GxElementsResults -> XML
        try {
            JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class); // JAXBException

            Marshaller marshallerObj = contextObj.createMarshaller(); // JAXBException
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // PropertyException

            StringWriter sw = new StringWriter();

            marshallerObj.marshal(result, sw); // JAXBException
            returnMessage = sw.getBuffer().toString();
        }  catch (PropertyException e) { // AFTER CALL
            returnMessage = util.getPropertyExceptionMessage(e);
        } catch (JAXBException e) { // AFTER CALL
            returnMessage = util.getJAXBExceptionMessage(e);
        }
        return returnMessage;
    }

    public String deleteKeywords(long customerAccountId, String keywordsRequestsXML) {
        ICampaignManagementService campaignManagement = null;
        CampaignManagementServiceLocator campaignServiceLocator = null;
        BasicHttpBinding_ICampaignManagementServiceStub stub = null;
        DeleteKeywordsRequest deleteKeywordsRequest = null;
        GA_Result result = new GA_Result();
        Util util = new Util();
        GxKeywordsRequest[] keywordsRequests = null;
        GxKeywordsAdGroupRequest keywordsAdGroupRequest = null;
        try {
            HashMap<String, String> properties = Info.getBingProperties();
            String namespace = properties.get("campaignNamespace");
            String url = properties.get("cagnaingURL");
            String userName = properties.get("username");
            String password = properties.get("password");
            String developerToken = properties.get("developerToken");
            String customerId = properties.get("customerId");
            String applicationToken = properties.get("applicationToken");

            campaignServiceLocator = new CampaignManagementServiceLocator();
            campaignServiceLocator.setBasicHttpBinding_ICampaignManagementServiceEndpointAddress(url);
            campaignManagement = campaignServiceLocator.getBasicHttpBinding_ICampaignManagementService(); // ServiceException
            stub = (BasicHttpBinding_ICampaignManagementServiceStub) campaignManagement;

            // Set header parameters
            stub.setHeader(namespace, "UserName", userName);
            stub.setHeader(namespace, "Password", password);
            stub.setHeader(namespace, "DeveloperToken", developerToken);
            stub.setHeader(namespace, "CustomerId", customerId);
            stub.setHeader(namespace, "CustomerAccountId", customerAccountId);
            stub.setHeader(namespace, "ApplicationToken", applicationToken);

            // Parse keywordRequests from XML
            keywordsRequests = util.keywordsRequestsFromXML(keywordsRequestsXML); // IllegalArgumentException, GxException, ParserConfigurationException, SAXException, IOException
            if (keywordsRequests.length == 0) {
                throw new GxItemException("No KeywordsRequests were found");
            }

            for (int k=0; k<keywordsRequests.length; k++) {
                Long gxCampaignId = keywordsRequests[k].getGxCampaignId();
                Long bingCampaignId =  keywordsRequests[k].getBingCampaignId();

                for (int j=0; j<keywordsRequests[k].getKeywordsAdGroupRequests().length; j++) {
                    keywordsAdGroupRequest = keywordsRequests[k].getKeywordsAdGroupRequests()[j];

                    // Set body parameters
                    deleteKeywordsRequest = new DeleteKeywordsRequest();
                    deleteKeywordsRequest.setAdGroupId(keywordsAdGroupRequest.getBingAdGroupId());
                    long[] keywordIds = new long[keywordsAdGroupRequest.getKeywords().length];
                    for (int i=0; i<keywordIds.length; i++) {
                        if (keywordsAdGroupRequest.getKeywords()[i].getId() == null) {
                            keywordIds[i] = -1;
                        } else {
                            keywordIds[i] = keywordsAdGroupRequest.getKeywords()[i].getId();
                        }
                    }
                    deleteKeywordsRequest.setKeywordIds(keywordIds);

                    try {
                        // Call WS
                        DeleteKeywordsResponse deleteKeywordsResponse = campaignManagement.deleteKeywords(deleteKeywordsRequest); // RemoteException, ApiFaultDetail, AdApiFaultDetail

                        // Call succeeded with no errors

                        // Create the return object

                        /*result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setSpecificTrackingId(trackingId);
                        result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setGxAdGroupId(keywordsAdGroupRequest.getGxAdGroupId());
                        result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].setBingAdGroupId(keywordsAdGroupRequest.getBingAdGroupId());
                        result.getElementsCampaignsResultCollection()[k].getElementsAdGroupsResults()[j].createElementCollection(keywordsAdGroupRequest.getKeywords().length);
                        */
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GxKeyword gxKW = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);

                            GA_ResultItem resultItem = new GA_ResultItem(deleteKeywordsResponse.getPartialErrors(), i);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.CampaignId = bingCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.AdGroupId = keywordsAdGroupRequest.getBingAdGroupId();
                            resultItem.CriterionGxId = gxKW.getGxId();
                            resultItem.CriterionId = gxKW.getId();

                            result.Items.add(resultItem);
                        }
                    } catch (ApiFaultDetail fault) { // IN CALL
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GxKeyword gxKW = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);

                            GA_ResultItem resultItem = new GA_ResultItem(fault, i);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = gxKW.getGxId();

                            result.Items.add(resultItem);
                        }
                    } catch (AdApiFaultDetail fault) { // IN CALL
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GxKeyword gxKW = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);

                            GA_ResultItem resultItem = new GA_ResultItem(fault);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = gxKW.getGxId();

                            result.Items.add(resultItem);
                        }
                    } catch (RemoteException e) { // IN CALL
                        for (int i=0; i< keywordsAdGroupRequest.getKeywords().length; i++) {
                            GxKeyword gxKW = ((GxKeyword) keywordsAdGroupRequest.getKeywords()[i]);

                            GA_ResultItem resultItem = new GA_ResultItem(e);

                            resultItem.SubCampaignGxId = gxCampaignId;
                            resultItem.AdGroupGxId = keywordsAdGroupRequest.getGxAdGroupId();
                            resultItem.CriterionGxId = gxKW.getGxId();

                            result.Items.add(resultItem);
                        }
                    }
                }
            }
        } catch (GxException e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        } catch (Exception e) { // BEFORE CALL
            result.Items.add(new GA_ResultItem(e));
        }

        String returnMessage = null;
        // GxElementsResults -> XML
        try {
            JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class); // JAXBException

            Marshaller marshallerObj = contextObj.createMarshaller(); // JAXBException
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // PropertyException

            StringWriter sw = new StringWriter();

            marshallerObj.marshal(result, sw); // JAXBException
            returnMessage = sw.getBuffer().toString();
        }  catch (PropertyException e) { // AFTER CALL
            returnMessage = util.getPropertyExceptionMessage(e);
        } catch (JAXBException e) { // AFTER CALL
            returnMessage = util.getJAXBExceptionMessage(e);
        }
        return returnMessage;
    }

    public ArrayList<BingKeyword> getKeywordsByAdGroupId(long customerAccountId, long adGroupId){
        BasicHttpBinding_ICampaignManagementServiceStub stub = null;
        ArrayList<BingKeyword> bingKeywords = new ArrayList<BingKeyword>();
        try{
            HashMap<String, String> properties = Info.getBingProperties();
            String namespace = properties.get("campaignNamespace");
            String url = properties.get("campaignURL");
            String userName = properties.get("username");
            String password = properties.get("password");
            String developerToken = properties.get("developerToken");
            String customerId = properties.get("customerId");
            String applicationToken = properties.get("applicationToken");

            CampaignManagementServiceLocator locator = new CampaignManagementServiceLocator();
            locator.setBasicHttpBinding_ICampaignManagementServiceEndpointAddress(url);
            namespace = locator.getServiceName().getNamespaceURI();
            stub = (BasicHttpBinding_ICampaignManagementServiceStub) locator.getBasicHttpBinding_ICampaignManagementService();

            stub.clearHeaders();

            stub.setHeader(namespace, "UserName", userName);
            stub.setHeader(namespace, "Password", password);
            stub.setHeader(namespace, "DeveloperToken", developerToken);
            stub.setHeader(namespace, "CustomerId", customerId);
            stub.setHeader(namespace, "CustomerAccountId", customerAccountId);

            GetKeywordsByAdGroupIdRequest request = new GetKeywordsByAdGroupIdRequest();
            request.setAdGroupId(adGroupId);

            GetKeywordsByAdGroupIdResponse response = stub.getKeywordsByAdGroupId(request);

            Keyword[] keywords = response.getKeywords();

            bingKeywords = new ArrayList<BingKeyword>();

            for (Keyword keyword : keywords){

                BingKeyword bingKeyword = new BingKeyword();
                bingKeyword.DestinationUrl = keyword.getDestinationUrl();
                bingKeyword.Id = keyword.getId();
                bingKeyword.MatchType = keyword.getMatchType();
                bingKeyword.Param1 = keyword.getParam1();
                bingKeyword.Param2 = keyword.getParam2();
                bingKeyword.Param3 = keyword.getParam3();
                bingKeyword.Status = keyword.getStatus();
                bingKeyword.Text = keyword.getText();
                bingKeywords.add(bingKeyword);
            }

            return bingKeywords;

        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (ServiceException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return bingKeywords;
    }


    private boolean compareKeywords(BingKeyword bingKeyword, GxKeyword gxKeyword){

        return (
                bingKeyword.Text.equalsIgnoreCase(gxKeyword.getText()) &&
                bingKeyword.Status.getValue().equalsIgnoreCase(gxKeyword.getStatus().getValue()) &&
                /*bingKeyword.Param1.equalsIgnoreCase(gxKeyword.getParam1()) &&
                bingKeyword.Param2.equalsIgnoreCase(gxKeyword.getParam2()) &&
                bingKeyword.Param3.equalsIgnoreCase(gxKeyword.getParam3()) && */
                bingKeyword.MatchType.getValue().equalsIgnoreCase(gxKeyword.getMatchType().getValue())
                );

    }

    private Long isCreatedKeyword(ArrayList<BingKeyword> bingKeywords, GxKeyword gxKeyword){
        Long isCreated = 0L;
        for (BingKeyword keyword : bingKeywords){
            if (compareKeywords(keyword, gxKeyword)){
                isCreated = keyword.Id;
                break;
            }
        }
        return isCreated;
    }

}
